package controllers

import dao._
import play.api.mvc._
import tool.Tool
import utils.Utils

import java.io.File
import javax.inject.Inject
import scala.concurrent.Await
import scala.concurrent.duration.Duration
import models.Tables._
import implicits.Implicits._
import upickle.default._
import scala.concurrent.ExecutionContext.Implicits.global

/**
 * Created by yz on 16/9/2021
 */
class DataInsertController @Inject()(cc: ControllerComponents)(
  implicit val basicDao: BasicDao,
  implicit val cdsDao: CdsDao,
  implicit val pepDao: PepDao,
  implicit val annoDao: AnnoDao,
  implicit val tpmDao: TpmDao,
  implicit val basic344Dao: Basic344Dao,
  implicit val basic344CdsDao: Basic344CdsDao,
  implicit val basic344PepDao: Basic344PepDao,
  implicit val basic344TpmDao: Basic344TpmDao,
  implicit val expH2Dao: ExpH2Dao,
) extends AbstractController(cc) {

  val parentDir = new File("E:\\nut_database\\test")

  def productBasic344PepFile = Action.async { implicit request =>
    basic344PepDao.selectAll.map { rows =>
      val lines = rows.flatMap { row =>
        List(s">${row.geneId}", row.pep)
      }
      lines.toList.toFile(new File(parentDir, "344.pep"))
      Ok("success")
    }
  }

  def insertExpH2 = Action {
    val file = new File(parentDir, "Macadamia integrifolia H2 expression matrix.xlsx")
    val lines = file.xlsxLines()
    val headers = lines.head.drop(1)
    val rows = lines.drop(1).map { columns =>
      val values = columns.drop(1).map(_.toDouble)
      val map = headers.zip(values).toSeqMap
      ExpH2Row(
        geneId = columns(0),
        value = writeJs(map)
      )
    }
    Await.result(expH2Dao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(expH2Dao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

  def insertBasic344Tpm = Action {
    val file = new File(parentDir, "Macadamia integrifolia HAES344 expression matrix.xlsx")
    val lines = file.xlsxLines()
    val headers = lines.head.drop(1)
    val rows = lines.drop(1).map { columns =>
      val values = columns.drop(1).map(_.toDouble)
      val map = headers.zip(values).toSeqMap
      Basic344TpmRow(
        geneId = columns(0),
        value = writeJs(map)
      )
    }
    Await.result(basic344TpmDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(basic344TpmDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

  def insertTpm = Action {
    val file = new File(parentDir, "genes.TPM.tab.xls")
    val rows = file.txtLines.drop(1).map { columns =>
      TpmRow(
        geneName = columns(0).replaceAll("^gene-", ""),
        shoot = columns(1).toDouble,
        leaf = columns(2).toDouble,
        flower = columns(3).toDouble
      )
    }
    Await.result(tpmDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(tpmDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

  def insertAnno = Action {
    val basicFile = new File(parentDir, "geneInfo.txt")
    val basicRows = basicFile.txtLines.lineSeqMap.map { map =>
      BasicRow(
        id = map("protein_id"),
        species = "Macadamia integrifolia",
        chr = map("sequence_name"),
        start = map("start").toInt,
        end = map("end").toInt,
        description = map("product"),
        strand = map("strand"),
        geneName = map("gene_name"),
        locus = s"${map("sequence_name")}:${map("start")}-${map("end")}"
      )
    }
    val basicMap = basicRows.map { x => (x.id, x) }.toMap
    val file = new File(parentDir, "annotation.table.txt")
    val rows = file.txtLines.lineSeqMap.map { map =>
      val id = map("#Qeury_name")
      val basicRow = basicMap(id)
      AnnoRow(
        id = id,
        qeuryLength = map("Qeury_length").toInt,
        nrTophitName = map("NR_tophit_name"),
        nrTophitDescrip = map("NR_tophit_descrip"),
        nrTopSimil = map("NR_top_%-Simil"),
        swissTophitName = map("Swiss_tophit_name"),
        swissprotTophitDescrip = map("Swissprot_tophit_descrip"),
        swissprotTopSimil = map("Swissprot_top_%-Simil"),
        gos = map("GOs"),
        cog = map("COG/KOG"),
        function = map("Function"),
        description = basicRow.description,
        strand = basicRow.strand,
        geneName = basicRow.geneName,
        locus = basicRow.locus,
        ko = map("KO/Gene_ID"),
        keggGeneName = map("KEGG_GENE_NAME")
      )
    }
    Await.result(annoDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(annoDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

  def insertBasic = Action {
    val file = new File(parentDir, "geneInfo.txt")
    val rows = file.txtLines.lineSeqMap.map { map =>
      BasicRow(
        id = map("protein_id"),
        species = "Macadamia integrifolia",
        chr = map("sequence_name"),
        start = map("start").toInt,
        end = map("end").toInt,
        description = map("product"),
        strand = map("strand"),
        geneName = map("gene_name"),
        locus = s"${map("sequence_name")}:${map("start")}-${map("end")}"
      )
    }
    Await.result(basicDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(basicDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

  def insertBasic344Cds = Action {
    val file = new File(parentDir, "cds.fa")
    val rows = Tool.getBasic344Cds(file)
    Await.result(basic344CdsDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(basic344CdsDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

  def insertCds = Action {
    val file = new File(parentDir, ".cds.fa")
    val rows = Tool.getCds(file)
    Await.result(cdsDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(cdsDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

  def insertBasic344Pep = Action {
    val file = new File(parentDir, "pep.fa")
    val rows = Tool.getBasic344Peps(file)
    Await.result(basic344PepDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(basic344PepDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")

  }

  def insertPep = Action {
    val file = new File(parentDir, ".pep.fa")
    val rows = Tool.getPeps(file)
    Await.result(pepDao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(pepDao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")

  }

  def insertBasic344 = Action {
    val file = new File(parentDir, "GWHBAUK00000000.1.txt")
    val rows = file.txtLines.lineSeqMap.map { map =>
      Basic344Row(
        id = map("ID"),
        chr = map("Chromosome"),
        start = map("start").toInt,
        end = map("end").toInt,
        strand = map("strand"),
        locus = s"${map("Chromosome")}:${map("start")}-${map("end")}"
      )
    }
    Await.result(basic344Dao.deleteAll, Duration.Inf)
    val startTime = System.currentTimeMillis()
    val rowsSize = rows.size
    val num = 1000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(basic344Dao.insertAll(x), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + Utils.getTime(startTime))
    }
    println("insert table successfully!" + Utils.getTime(startTime))
    Ok("success!")
  }

}
